Skip to content

Conversation

@emdashcodes
Copy link
Contributor

@emdashcodes emdashcodes commented Oct 15, 2025

This PR introduces a new REST endpoint for discovering and listing ability categories.

Why

Following PRs #102 and #114 which introduced the categories system, we need a way to expose category information via the REST API so that it can be used in places like the command pallete, agents, etc.

External systems and AI agents need to discover what categories exist before they can effectively filter and query abilities.

Additionally, the existing abilities endpoints were accessible to any authenticated user with read capability, which could return meta information about available capabilities to subscribers (though, I believe they would need an application password setup). I've updated the permission check to require manage_options instead, which I think might be better for the endpoints. What do you think?

How

Created a new WP_REST_Abilities_Categories_Controller:

  • New endpoints - GET /wp/v2/abilities/categories (list) and GET /wp/v2/abilities/categories/{slug}
  • _links - Each category response includes self, collection, and abilities links for API discoverability
  • Pagination - Supports pagination with page/per_page parameters (default 50, max 100)
  • Admin-only access - Changed permission check from read to manage_options for both categories and abilities endpoints (see note above)
  • Test cases - Test cases covering list operations, permissions, pagination, links, and edge cases

How to Test

Make sure that you have a few categories and Abilities registered.

npm run test:php
npm run lint:php
  1. List categories

    curl -u "admin:APP_PASSWORD" \
      https://example.com/wp-json/wp/v2/abilities/categories
    • Should return array of categories with pagination headers
    • Each category should include pagination links to self, collection, and abilities
  2. Get single category

    curl -u "admin:APP_PASSWORD" \
      https://example.com/wp-json/wp/v2/abilities/categories/data-retrieval
    • Should return category details with slug, label, description, meta
  3. Test pagination

    curl -u "admin:APP_PASSWORD" "https://example.com/wp-json/wp/v2/abilities/categories?per_page=2"
    • Check X-WP-Total and X-WP-TotalPages headers
  4. Test filtering abilities by category

    curl -u "admin:APP_PASSWORD" \
      "https://example.com/wp-json/wp/v2/abilities?category=data-retrieval"
    • Should return only abilities in the specified category
  5. Test permissions

    # Without authentication (should fail with 401)
    curl https://example.com/wp-json/wp/v2/abilities/categories
    
    # With non-admin user (should fail with 403)
    curl -u "subscriber:APP_PASSWORD" \
      https://example.com/wp-json/wp/v2/abilities/categories
  6. Test 404 handling

    curl -u "admin:APP_PASSWORD" \
      https://example.com/wp-json/wp/v2/abilities/categories/non-existent
    • Should return 404 with rest_category_not_found error code

@emdashcodes emdashcodes self-assigned this Oct 15, 2025
@emdashcodes emdashcodes added the [Type] Enhancement New feature or request label Oct 15, 2025
@codecov
Copy link

codecov bot commented Oct 15, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 88.50%. Comparing base (e8d0efd) to head (ee2039e).
⚠️ Report is 1 commits behind head on trunk.

Additional details and impacted files
@@             Coverage Diff              @@
##              trunk     #120      +/-   ##
============================================
+ Coverage     86.65%   88.50%   +1.84%     
- Complexity      148      162      +14     
============================================
  Files            18       19       +1     
  Lines           982     1140     +158     
  Branches         92       92              
============================================
+ Hits            851     1009     +158     
  Misses          131      131              
Flag Coverage Δ
javascript 93.04% <ø> (ø)
unit 87.36% <100.00%> (+2.65%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@github-actions
Copy link

github-actions bot commented Oct 15, 2025

The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the props-bot label.

If you're merging code through a pull request on GitHub, copy and paste the following into the bottom of the merge commit message.

Co-authored-by: emdashcodes <[email protected]>
Co-authored-by: gziolo <[email protected]>

To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook.

@gziolo
Copy link
Member

gziolo commented Oct 15, 2025

Additionally, the existing abilities endpoints were accessible to any authenticated user with read capability, which could return meta information about available capabilities to subscribers (though, I believe they would need an application password setup). I've updated the permission check to require manage_options instead, which I think might be better for the endpoints. What do you think?

This largely limits who can consume these abilities. For example, plugin developer no longer will be able to integrate a simple readonly ability on the client executed upon user interaction when they are only logged in but with read permissions. This essentially means abilities become discoverable on the client only for users with high-level of permissions. One of the future integrations for abilities is Command Palette where I would expect all logged in users would be able to see at least subset of abilities listed in the UI.

@gziolo
Copy link
Member

gziolo commented Oct 15, 2025

Maybe the alternative solution for starters is to prevent exposure of meta for categories in view context and distinguish permissions based on that context, too. Additionally, expose only 4 allowed meta.annotations for abilities list endpoint to ensure nothing sensitive gets exposed to less privileged users in view context, expose all meta in edit context. In embed context we can simply continue to skip meta field.

@emdashcodes
Copy link
Contributor Author

This largely limits who can consume these abilities. [...]

True and that is a good valid use case. It just kind of stood out to me as maybe too open as I was introducing another endpoint. I've backed it out for now, however ee2039e

@gziolo
Copy link
Member

gziolo commented Oct 15, 2025

I checked the code and I don’t have any other feedback. The implementation proposed looks solid from my perspective. Thank you for helping here!

@gziolo
Copy link
Member

gziolo commented Oct 15, 2025

Aside, I’m happy to discuss how to ensure we don’t accidentally try to send through REST API class instances or callables if someone adds them to meta. In addition to the considerations that maybe we should limite these custom meta to edit context. This should be tackled separately.

@gziolo gziolo merged commit 118cd0a into trunk Oct 16, 2025
21 checks passed
@gziolo gziolo deleted the add/categories-rest-endpoints branch October 16, 2025 10:53
@gziolo gziolo added this to the pre WP 6.9 milestone Oct 16, 2025
gziolo added a commit that referenced this pull request Oct 16, 2025
* add: category listing endpoints for the REST API

* update: back out permissions check changes

Co-authored-by: emdashcodes <[email protected]>
Co-authored-by: gziolo <[email protected]>
jonathanbossenger added a commit that referenced this pull request Oct 21, 2025
jonathanbossenger added a commit that referenced this pull request Oct 21, 2025
jonathanbossenger added a commit that referenced this pull request Oct 21, 2025
* Docs refactor in prepartion for WordPress 6.9

Moved all PHP related docs to the php-api.md
Created new README.md file with correct doc ordering
Removed doc file numbering
Updating main repo README.md doc links

* Updating hooks

Adding reference for abilities_api_init

Moving hook registration in code examples above callback function for better readability

* Adding other category functions to PHP API

* Update README.md with direct link to docs README

* Adding ability_class information and example (#122)

* Adding ability_class information and example

* Adding contributing docs to Documenation section in the readme

* Fixing outdated link

* PR review updates

* Adding REST API docs updates from #120

* JavaScript client updates from #120

Co-authored-by: jonathanbossenger <[email protected]>
Co-authored-by: gziolo <[email protected]>
Co-authored-by: aaronware <[email protected]>
Co-authored-by: galatanovidiu <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

[Type] Enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants